package com.example.springbootdemo.job;

import com.example.springbootdemo.model.ChooseDataInfo;
import com.example.springbootdemo.model.ChooseInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.LongAdder;

@Component
@Slf4j
public class ChooseDataOperateJob implements ApplicationRunner {

    private boolean isLoad = false;

    private final String defaultResultFile = "result.txt";
    private final String defaultChooseFile = "choose.txt";

    private final String splitFlag = "\\|";

    @Value("${basePath:d:/choose}")
    private String basePath;


    private List<String> getFileContext(String absolutePath, String fileName) throws IOException {
        String resultFilePath = String.format("%s/%s", StringUtils.defaultIfBlank(absolutePath, basePath), fileName);

        // 读取ip数据
        File resultFile = new File(resultFilePath);
        if (resultFile.exists()) {
            List<String> lines = new ArrayList<>();
            try (FileInputStream fis = new FileInputStream(resultFile);
                 InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
                 BufferedReader br = new BufferedReader(isr)) {

                String line;
                while ((line = br.readLine()) != null) {
                    lines.add(line);
                }

                return lines;
            }
        }
        return null;
    }

    /**
     * 数据落盘
     * @param lines 落盘数据
     */
    public void doDumpData(List<String> lines, String fileName) throws IOException {
        if (CollectionUtils.isEmpty(lines)) {
            return;
        }

        String resultFilePath = Paths.get(basePath, fileName).toString();
        Path filePath = Paths.get(resultFilePath);

        // 如果文件不存在，创建文件及所有必要的父目录
        if (!Files.exists(filePath)) {
            Files.createDirectories(filePath.getParent()); // 确保目录存在
            Files.createFile(filePath); // 创建文件
            log.info("{} - file has created", resultFilePath);
        }

        try (FileOutputStream fos = new FileOutputStream(filePath.toFile());
             OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
             BufferedWriter bw = new BufferedWriter(osw)) {

            for (String line : lines) {
                bw.write(line);
                bw.newLine();
            }
        }
    }

    public void loadData() throws IOException {
        Map<String, LongAdder> statisticMap = ChooseDataInfo.getStatisticMap();
        List<String> resultContext = getFileContext(basePath, defaultResultFile);
        if (!CollectionUtils.isEmpty(resultContext)) {
            resultContext.forEach(line -> {
                String[] split = line.split(splitFlag);
                String chooseResult = split[0].toUpperCase();
                String number = split[1];
                LongAdder longAdder = new LongAdder();
                longAdder.add(Long.parseLong(number));
                statisticMap.put(chooseResult, longAdder);
            });
        }

        // 读取选择数据
        List<String> chooseContext = getFileContext(basePath, defaultChooseFile);
        Map<String, ChooseInfo> chooseMap = ChooseDataInfo.getChooseMap();
        if (!CollectionUtils.isEmpty(chooseContext)) {
            chooseContext.forEach(line -> {
                String[] split = line.split(splitFlag);
                if (split.length == 3) {
                    ChooseInfo chooseInfo = new ChooseInfo(split[0], split[1], split[2]);
                    chooseMap.put(chooseInfo.getIp(), chooseInfo);
                }
            });
        }
    }


    @Override
    public void run(ApplicationArguments args) throws Exception {
        List<String> clearData = args.getOptionValues("loadData");

        if (clearData != null && clearData.stream().anyMatch("true"::equals)) {
            loadData();
        }
        isLoad = true;
    }

    /**
     * 定时将数据落盘
     * 每30秒执行一次
     */
    @Scheduled(fixedRate = 10000)
    public void dumpData() throws IOException {
        if (!isLoad) {
            return;
        }

        List<String> resultList = new ArrayList<>();
        ChooseDataInfo.getStatisticMap()
                .forEach((key, value) -> resultList.add(String.format("%s|%s", key, value.longValue())));
        doDumpData(resultList, defaultResultFile);

        List<String> chooseList = new ArrayList<>();
        ChooseDataInfo.getChooseMap()
                .forEach((key, value) -> chooseList.add(String.format("%s|%s|%s", value.getChoose(), value.getIp(), value.getLocalDateTime())));
        doDumpData(chooseList, defaultChooseFile);


        log.info("dump data");
    }
}
